using Microsoft.EntityFrameworkCore;
using RAG.Domain.Entities.App;
using Pgvector.EntityFrameworkCore;
using Pgvector;

namespace RAG.Infrastructure.Data;

public class RagAIDbContext : DbContext
{
    public RagAIDbContext(DbContextOptions<RagAIDbContext> options) : base(options)
    {
    }

    // 实体DbSet
    public DbSet<Users> Users { get; set; }
    public DbSet<Roles> Roles { get; set; }
    public DbSet<Permissions> Permissions { get; set; }
    public DbSet<Sessions> Sessions { get; set; }
    public DbSet<Conversations> Conversations { get; set; }
    public DbSet<Documents> Documents { get; set; }
    public DbSet<DocumentChunks> DocumentChunks { get; set; }
    public DbSet<KnowledgeBase> KnowledgeBase { get; set; }
    public DbSet<SystemLogs> SystemLogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // 启用pgvector扩展
        modelBuilder.HasPostgresExtension("vector");

        // 配置向量列 - 使用1024维向量
        modelBuilder.Entity<KnowledgeBase>(entity =>
        {
            entity.Property(e => e.Embedding)
                .HasColumnType("vector(1024)")
                .HasConversion(
                    v => new Vector(v),
                    v => v.ToArray(),
                    new Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<float[]>(
                        (c1, c2) => c1!.SequenceEqual(c2!),
                        c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
                        c => c.ToArray()));

            // 创建向量索引 - 使用HNSW索引和余弦距离
            entity.HasIndex(e => e.Embedding)
                .HasMethod("hnsw")
                .HasOperators("vector_cosine_ops");

            // 配置字段长度
            entity.Property(e => e.DocumentType).HasMaxLength(100);
            entity.Property(e => e.EmbeddingType).HasMaxLength(50);
            entity.Property(e => e.ImageUrl).HasMaxLength(2000);
            entity.Property(e => e.Source).HasMaxLength(1000);
            entity.Property(e => e.Title).HasMaxLength(500);

            // 配置与DocumentChunks的关系
            entity.HasOne(kb => kb.Chunk)
                .WithMany(dc => dc.KnowledgeBase)
                .HasForeignKey(kb => kb.ChunkId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // 配置多对多关系
        modelBuilder.Entity<Users>()
            .HasMany(u => u.Roles)
            .WithMany(r => r.Users)
            .UsingEntity(j => j.ToTable("UserRoles"));

        modelBuilder.Entity<Roles>()
            .HasMany(r => r.PermissionList)
            .WithMany(p => p.Roles)
            .UsingEntity(j => j.ToTable("RolePermissions"));

        // 配置一对多关系（让EF Core自动管理外键）
        modelBuilder.Entity<DocumentChunks>()
            .HasOne(dc => dc.Document)
            .WithMany(d => d.DocumentChunks)
            .HasForeignKey("DocumentId"); // 使用字符串指定外键名称

        // 配置Documents与Users的关系
        modelBuilder.Entity<Documents>()
            .HasOne(d => d.User)
            .WithMany(u => u.Documents)
            .HasForeignKey("UserId"); // 使用字符串指定外键名称

        // 配置表名
        modelBuilder.Entity<Users>().ToTable("Users");
        modelBuilder.Entity<Roles>().ToTable("Roles");
        modelBuilder.Entity<Permissions>().ToTable("Permissions");
        modelBuilder.Entity<Sessions>().ToTable("Sessions");
        modelBuilder.Entity<Conversations>().ToTable("Conversations");
        modelBuilder.Entity<Documents>().ToTable("Documents");
        modelBuilder.Entity<DocumentChunks>().ToTable("DocumentChunks");
        modelBuilder.Entity<KnowledgeBase>().ToTable("KnowledgeBase");
        modelBuilder.Entity<SystemLogs>().ToTable("SystemLogs");

        // 配置索引
        modelBuilder.Entity<Users>()
            .HasIndex(u => u.UserName)
            .IsUnique();

        modelBuilder.Entity<Users>()
            .HasIndex(u => u.Email)
            .IsUnique();

        modelBuilder.Entity<Roles>()
            .HasIndex(r => r.RoleName)
            .IsUnique();

        modelBuilder.Entity<Permissions>()
            .HasIndex(p => p.PermissionName)
            .IsUnique();
    }
}